from django.http import HttpResponse
import urllib
import urllib2
from urllib2 import URLError
import json
import re
import util
import uuid
from socket import timeout
from datetime import date
from api.models import Author, Price, Book
from django.db import IntegrityError
import os
'''
Created on Apr 4, 2011

@author: Miles
'''

NAMESPACE_COLLECTOR = 'api.collector'

mandatory_fields = [['author'],
                    ['title'],
                    ['isbn_10', 'isbn_13'],
                    ['price_new', 'price_used', 'price_market'],
                    ['purchase_url'],]
                    #['description']]

item_fields = ['author', 'title', 
          'isbn_10', 'isbn_13',
          'price',
          'description',
          'image_url'
          ]

price_fields = ['price_new', 'price_used', 'price_market',
               'purchase_url']

symbols = ['"*', '[...]', '</?\w+\s+[^>]*>']

def search(request):
    args = dict(request.GET.items())
    opts = {'indent': None, 'max': 0, 'offset': 0}
    for o in ['indent', 'max', 'offset']:
        if o in args:
            opts[o] = int(args[o])
            del args[o]
    
    extParams = urllib.urlencode({"action":"retrieve"})

    extSock = urllib2.urlopen("http://teamvilot.com/?%s" % (extParams))

    extractors = json.loads(extSock.read())    
            
    isbnmap = {}

    for extractor in extractors:
        try:
            sock = urllib2.urlopen(extractor['api_url'] + "?%s" % urllib.urlencode(args),timeout=10)
            results = json.loads(sock.read())

        except URLError:
            results = None
        except ValueError:
            results = None
        except timeout:
            results = None
            
        print(extractor['name'])
            
        if results:            
            for result in results:
                formatted = {}
                rfields = result['attributes']
            
                if (checkMandatoryFields(rfields) and checkIsbns(rfields)):
                    isbn = getIsbn(rfields)

                    if isbn is not None:                
                        if isbn in isbnmap:
                            formatted = isbnmap[isbn]
                            prices = convertPrices(getFields(rfields, price_fields), extractor['name'])
                            for price in prices:
                                formatted['prices'].append(price)
                            
                            if 'isbn_10' not in formatted and 'isbn_10' in rfields:
                                formatted['isbn_10'] = rfields['isbn_10']
                        
                            if 'description' in formatted:
                                formatted['description'] = remove_symbols(formatted['description'])
                            if 'description' not in formatted and 'description' in rfields:
                                formatted['description'] = remove_symbols(rfields['description'])    
                                                    
                            isbnmap[isbn] = formatted
                        else:
                            formatted = getFields(rfields, item_fields)
                            prices = convertPrices(getFields(rfields, price_fields), extractor['name'])
                            formatted['isbn_13'] = isbn
                            formatted['prices'] = []
                            for price in prices:
                                formatted['prices'].append(price)

                            formatted['uuid'] = int(str(uuid.uuid3(uuid.NAMESPACE_X500, str(isbn)).int)[:16])
                            
                            isbnmap.update({isbn : formatted})  
              
    results = isbnmap.values()   
    
    insertResults(results)

    return HttpResponse(json.dumps(results, indent=opts['indent']), mimetype='application/json')
    
def checkMandatoryFields(fields):
    valid = True
    for field in mandatory_fields:
        sub_valid = False
        
        for subfield in field:
            sub_valid = subfield or (subfield in mandatory_fields and fields[subfield])
        
        valid = valid and sub_valid
        
    return valid
   
def getFields(fields, item_set):
    return dict((k, v) for k, v in fields.items() if k in item_set)

def convertPrices(price, vendor):
    prices = []
    if 'price_new' in price and price['price_new'] != '':
        prices.append({'condition' : 'new',
         'price' : price['price_new'],
         'purchase_url' : price['purchase_url'],
         'vendor' : vendor,
         'updated' : '00000'})
    if 'price_used' in price and price['price_used'] != '':
        prices.append({'condition' : 'used',
         'price' : price['price_used'],
         'purchase_url' : price['purchase_url'],
         'vendor' : vendor,
         'updated' : '00000'})
    if 'price_market' in price and price['price_market'] != '':
        prices.append({'condition' : 'market',
         'price' : price['price_market'],
         'purchase_url' : price['purchase_url'],
         'vendor' : vendor,
         'updated' : '00000'})
        
    return prices

def checkUnicode(string):
    if re.search('\u', string):
        return 1
    else:
        return 0
        
def checkIsbns(fields):
    if 'isbn_10' in fields and fields['isbn_10'] is not None:
        isbn_10 = fields['isbn_10'].strip()
        try:
            int(isbn_10)
            
        except ValueError:
            return False
        
        return util.valid_isbn_13(util.isbn_10_13(isbn_10))
    elif 'isbn_13' in fields and fields['isbn_13'] is not None:
        isbn_13 = fields['isbn_13'].strip()
        try:
            int(isbn_13)
            
        except ValueError:
            return False
          
        if len(isbn_13) == 10:
            return util.valid_isbn_13(util.isbn_10_13(isbn_13))
        elif len(isbn_13) == 13:
            return util.valid_isbn_13(isbn_13)
    else:
        return False    
    
def getIsbn(fields):
    if 'isbn_10' in fields and fields['isbn_10'] is not None:
        return (util.isbn_10_13(fields['isbn_10'].strip()))
    elif 'isbn_13' in fields and fields['isbn_13'] is not None:
        if len(fields['isbn_13'].strip()) == 10:
            return util.isbn_10_13(fields['isbn_13'].strip())
        elif len(fields['isbn_13'].strip()) == 13:
            return (fields['isbn_13']).strip()
    else:
        return None
    
def insertResults(results):
    for result in results:
        desc = ''
        img_url = ''
                
        if 'description' in result:
            desc = result['description']
        if 'image_url' in result:
            img_url = result['image_url']
        try:
            b = Book.objects.create(uuid=result['uuid'], title=result['title'],
                             isbn_13=result['isbn_13'], description=desc, image_url=img_url)
            
        except IntegrityError:
            b = Book(uuid=result['uuid'])
            
        for price in result['prices']:
            Price.objects.create(book=b,price=round(float(price['price']), 2),
                                  purchase_url=price['purchase_url'], condition=price['condition'],
                                  vendor=price['vendor'])
        if 'author' in result:    
            for authors in result['author']:
                try:
                    Author.objects.create(book=b,author=authors)
                except IntegrityError:
                    None

def getResults(query):
    b = Book(title=query)
    

def remove_symbols(data):
    str = data
    for symbol in symbols:
        p = re.compile(symbol)
        str = p.sub('', str)
    
    return str
